//
// Created by SDSC\202100300261 on 23-11-17.
//

#include <iostream>
#include "Runner.h"
Runner::Runner(CodeTable* _code) {
    this->memory = new Memory(&_code -> codeTable);
    memory->push(0);
    memory->push(0);
    memory->push(0);
}
Runner::~Runner() {
    delete this->memory;
}

void Runner::run() {
    int cnt = 0;
    while(memory -> P < memory -> codes -> size()) {

        CodeEntry* codeEntry = memory -> getCode();
        switch (codeEntry -> opt) {
            case OPTS::LIT:
                runLit(codeEntry);
                break;
            case OPTS::LOD:
                runLod(codeEntry);
                break;
            case OPTS::STO:
                runSto(codeEntry);
                break;
            case OPTS::CAL:
                runCal(codeEntry);
                break;
            case OPTS::INT:
                runInt(codeEntry);
                break;
            case OPTS::JMP:
                runJmp(codeEntry);
                break;
            case OPTS::JPC:
                runJpc(codeEntry);
                break;
            case OPTS::OPR:
                runOpr(codeEntry);
                break;
            default:
                break;
        }
    }
}
/**
 * LIT：将常量送到S栈的栈顶；
 * L：0；
 * A：常量值；
 */
void Runner::runLit(CodeEntry* code) {
    memory -> push(code -> adr);
}
/**
 * LOD：将变量送到S栈的栈顶；
 * L：层差；
 * A：变量所在说明层的相对地址；
 */
void Runner::runLod(CodeEntry *code) {
    int adr = memory -> getLevelAdr(code -> level) + code -> adr;
    memory -> push(memory -> S[adr]);
}

/**
 * STO：将运行栈S的栈顶内容送入某变量单元中；
 * L：层差；
 * A：变量所在说明层的相对地址；
 * 操作完之后需要退栈
 */
void Runner::runSto(CodeEntry *code) {
    int adr = memory -> getLevelAdr(code -> level) + code -> adr;
    memory -> set(adr,memory -> pop());
}
/**
 * 调用，新过程的前三个位置依次为SL、DL、RA
 * SL为静态链，指向调用该过程的过程的数据空间基地址
 * DL为动态链，指向调用该过程的过程的基地址
 * RA为返回地址，指向调用该过程的指令的下一条指令
 * @param code
 */
void Runner::runCal(CodeEntry *code) {
    memory -> push(memory -> getLevelAdr(code -> level));
    memory -> push(memory -> B);
    memory -> push(memory -> P);
    memory -> B = memory -> T - 2;
    memory -> P = code -> adr;
}
/**
 * 申请分配空间，由于在调用过程时已经分配了SL、DL、RA三个位置，所以这里只需要将T指针向后移动adr-3即可
 * @param code
 */
void Runner::runInt(CodeEntry *code) {

    for(int i = 3;i < code -> adr;++i) {
        memory -> push(0);
    }
    //adr为需要分配的空间大小，3为静态链SL、动态链DL、返回地址RA
}
/**
 * 无条件跳转
 * @param code
 */
void Runner::runJmp(CodeEntry *code) {

    memory -> P = code -> adr;
}
/**
 * 条件跳转，如果栈顶为0则跳转
 * @param code
 */
void Runner::runJpc(CodeEntry *code) {
    if(memory -> pop() == 0) {
        memory -> P = code -> adr;
    }
}

/**
 * OPR：关系运算和算术运算；
 */
void Runner::runOpr(CodeEntry *code) {
    switch (code -> adr) {

        case 0:
           opr0();
           break;
        case 1:
            opr1();
            break;
        case 2:
            opr2();
            break;
        case 3:
            opr3();
            break;
        case 4:
            opr4();
            break;
        case 5:
             opr5();
             break;
        case 6:
            opr6();
            break;
        case 8:
            opr8();
            break;
        case 9:
            opr9();
            break;
        case 10:
            opr10();
            break;
        case 11:
            opr11();
            break;
        case 12:
            opr12();
            break;
        case 13:
            opr13();
            break;
        case 14:
            opr14();
            break;
        case 15:
            opr15();
            break;
        case 16:
            opr16();
            break;
        default:
            break;
   }
}
/**
 * OPR 0 0：过程调用结束后，返回调用点并退栈
 */
void Runner::opr0() {
    memory -> P = memory -> S[memory -> B + 2];//按照Base+2找到回去的PC断点
    memory -> B = memory -> S[memory -> B + 1];//按照Base+1找到回去的DL

}
/**
 * OPR 0 1：栈顶元素取反
 */
void Runner::opr1() {
    memory -> push( -memory -> pop());
}
/**
 * OPR 0 2：栈顶两个元素相加，退栈，结果值进栈
 */
void Runner::opr2() {
    int p1 = memory -> pop();
    int p2 = memory -> pop();
    memory -> push(p2 + p1);
}
/**
 * OPR 0 3：栈顶两个元素相减，退栈，结果值进栈
 */
void Runner::opr3() {
    int p1 = memory -> pop();
    int p2 = memory -> pop();
    memory -> push(p2 - p1);
}
/**
 * OPR 0 4：栈顶两个元素相乘，退栈，结果值进栈
 */
void Runner::opr4() {
    int p1 = memory -> pop();
    int p2 = memory -> pop();
    memory -> push(p2 * p1);
}
/**
 * OPR 0 5：栈顶两个元素相除，退栈，结果值进栈
 */
void Runner::opr5() {
    int p1 = memory -> pop();
    int p2 = memory -> pop();
    memory -> push(p2 / p1);
}
/**
 * OPR 0 6：栈顶元素的奇偶判断，结果值进栈
 */
void Runner::opr6() {
    memory -> push(memory -> pop() % 2);
}
/**
 * OPR 0 8：栈顶两个元素相等，退栈，结果值进栈
 */
void Runner::opr8() {
    int p1 = memory -> pop();
    int p2 = memory -> pop();
    memory -> push(p2 == p1 ? 1 : 0);
}
/**
 * OPR 0 9：栈顶两个元素不等，退栈，结果值进栈
 */
void Runner::opr9() {
    int p1 = memory -> pop();
    int p2 = memory -> pop();
    memory -> push(p2 != p1 ? 1 : 0);
}
/**
 * OPR 0 10：栈顶两个元素前者小于后者，退栈，结果值进栈
 */
void Runner::opr10() {
    int p1 = memory -> pop();
    int p2 = memory -> pop();
    memory -> push(p2 < p1 ? 1 : 0);
}

/**
 * OPR 0 11：栈顶两个元素前者大于等于后者，退栈，结果值进栈
 */
void Runner::opr11() {
    int p1 = memory -> pop();
    int p2 = memory -> pop();
    memory -> push(p2 >= p1 ? 1 : 0);
}
/**
 * OPR 0 12：栈顶两个元素前者大于后者，退栈，结果值进栈
 */
void Runner::opr12() {
    int p1 = memory -> pop();
    int p2 = memory -> pop();
    memory -> push(p2 > p1 ? 1 : 0);
}
/**
 * OPR 0 13：栈顶两个元素前者小于等于后者，退栈，结果值进栈
 */
void Runner::opr13() {
    int p1 = memory -> pop();
    int p2 = memory -> pop();
    memory -> push(p2 <= p1 ? 1 : 0);
}
/**
 * OPR 0 14：栈顶元素输出
 */
void Runner::opr14() {
    int p = memory -> pop();
    std::cout << p;
}
/**
 * OPR 0 15：输出换行
 */
void Runner::opr15() {
    std::cout << std::endl;
}
/**
 * OPR 0 16：从命令行读入一个输入置于栈顶
 */
void Runner::opr16() {
    int p;
    std::cin >> p;
    memory -> push(p);
}
